#include <stdio.h>

/**
 * https://www.bilibili.com/video/BV1vs411n7TH?p=2
 * 1.2.4 C语言的 32 个关键字, 其中:

数据类型关键字: 12个

控制语句关键字: 12个

存储类型关键字: 5个
    1.auto      : 定义"局部变量"(可省略)
    2.const     : 定义"常量", 相当于 Java 的 final, 常量的值不能修改 (/ˈkɒnst/ n.常量，常数)
    3.extern    : 可以在一个文件中引用另一个文件中定义的变量or函数. (/ˈekstɜːn/ adj.外面的；外来的；对外的)
    4.register  : 定义寄存器变量, 提高效率.(处理速度更快, CPU -> 寄存器 -> Cache -> 内存 -> 硬盘)
                  register 是建议型指令, 非命令型指令. if CPU 有空闲寄存器, 那么这个命令生效, 否则无效(会被定义在内存).
                  定义后, 在内存中没有这个变量的地址, 可防止反编译!
    5.static    : 静态变量/函数, 只会初始化1次, 在"数据区"存储
                  全局静态变量&静态函数: 仅可在本文件中使用, 不能外部 extern 引用!!! 相当于Java的private,


其它(类型)关键字: 3个
    1.sizeof    : 求指定数据类型在内存中的大小, 单位字节 byte
                  //返回值: size_t(typedef unsigned int size_t), 在 vcruntime.h 中定义.
                  //3种使用方式: sizeof(int);  sizeof(a);  sizeof a;
    2.typedef   : type define, 给数据类型取别名 & 定义函数指针
    3.volatile  : 防止编译器优化(有时候优化后,程序会出错). (/ˈvɒlətaɪl/ 不稳定的; 易挥发的)
 */


/*
 * extern 声明函数: extern可省略: https://www.bilibili.com/video/BV1vs411n7TH?p=57
 *                比如 max 函数写在 main 后面(或者写在其它.c 文件中), 但在 main 函数中调用了max方法, 会报错.
 *                这个声明就是告诉编译器, 后面某个地方(or其它文件)有这个函数.
 * extern 声明变量: 告诉编译器, 这个变量在这个函数的后面(or另外的 .c 文件中).
 *
 * extern 声明语句, 可写在方法中!!
 */
extern     void extern_test();
extern     void volatile_test();
extern     void static_test();
extern     int max(int a, int b);
/*extern*/ int add(int, int);      //声明方法的时候, 可省略 extern & 参数名
extern     float FLOAT_FROM_GLOBAL;//声明 Global.c 中的 全局常量

// 使用示例
int main() {
    //1.auto(可省略)
    auto  int a     = 2;

    /**
     * 2.const
     * C语言中, "不推荐" const 定义局部变量, 不安全, ∵指针可修改值.
     * ('全局'常量安全!!)
     */
    const int b = 3;             //定义常量
    const float f  = 3.111F;
    const char* str = "";        //字符串常量,相当于 final String?

    //3.extern, 可声明在函数中
    extern_test();

    //4.register
    register int d;              //i不是在内存里面, 而是寄存器里面, 在内存中没有这个变量的地址, 可防止反编译!
                                 //提高代码效率, 但register是建议型的指令, 而不是命令型的指令
                                 //如果有寄存器, 才把i放进去, 所以不是加了关键字就一定把i放进去

    //5.static
    static_test();


    //1.sizeof
    sizeof(10);                 //4Byte = 32位(根据CPU位数, 如果CPU是16位嵌入式系统, 就会返回2)

    //3.valatile
    volatile_test();

    return 0;
}

//3.extern, 可声明在函数中
void extern_test() {
    extern int add(int, int);
    extern float PI;        //也可直接定义在函数中使用.
    int va = add(1, 2);

    int f = 10, g = 91;
    int ma = max(f, g);
    printf("max = %d\n", ma);    //91
}

void holdA() {
    //1.静态局部变量, 只会初始化1次, 在"数据区"存储
    static int A = 5;
    printf("A = %d\n", A++);
}
//5.static
static int GLOBAL_B = 10;   //2.静态全局变量, 仅可在本文件中使用, 不能外部 extern 引用!!!
void static_test() {
    for (int i = 0; i < 5; ++i) {
        holdA();            //5, 6, 7, 8, 9
    }
}



//3.valatile
void volatile_test() {
    volatile int e = 100;       //防止编译器优化
    e += 5;
    //这儿, 外部设备改了i的值
    e += 10;
    //如果不加 volatile, 会被编译器优化: i += 15;
    //但是i会被外部设备修改, 所以就不会被优化
    printf("e = %d\n", e);
}

int max(int a, int b) {
    return a > b ? a : b;
}
int add(int a, int b) {
    return a + b;
}